package jmine.tec.purge.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;

import jmine.tec.persist.annotation.Alias;
import jmine.tec.persist.annotation.Constraint;
import jmine.tec.persist.annotation.Index;
import jmine.tec.purge.domain.enumx.PurgeStatus;

import org.hibernate.annotations.Type;
import org.hibernate.validator.NotNull;

import bancosys.tec.component.Documentation;
import bancosys.tec.persist.bussobj.PersistableBusinessObject;
import bancosys.tec.utils.date.Date;
import bancosys.tec.utils.date.Timestamp;

/**
 * Execução de expurgo.
 * 
 * @author Marcio Ribeiro (mmr)
 * @created Aug 8, 2011
 */
@Entity
@Table(name = "PURGE_REQUEST")
@Alias("PURREQ")
@SequenceGenerator(name = "SEQ_PURREQ", sequenceName = "SEQ_PURREQ")
@Documentation("LOG DE REQUISIÇÃO DE EXPURGO")
public class PurgeRequest extends PersistableBusinessObject {
    private Long id;

    private String userName;

    private String cfgName;

    private PurgeStatus status;

    private Timestamp requestStartTime;

    private Timestamp requestEndTime;

    private Date maxDate;

    private int totalItems;

    private int totalItemsPurged;

    private int maxWindowSize;

    private String errorMessage;

    /**
     * @return valor do campo id.
     */
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_PURREQ")
    @Column(name = "COD_PURGE_REQUEST", nullable = false)
    @Documentation("CÓDIGO DA EXECUÇÃO DE EXPURGO")
    public Long getId() {
        return id;
    }

    /**
     * Define valor para campo id.
     * 
     * @param id valor para campo id.
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * @return valor do campo purgeConfigId.
     */
    @NotNull
    @Column(name = "PURGE_CONFIG_NAME", nullable = false)
    @Documentation("NOME DA CONFIGURAÇÃO DE EXPURGO")
    public String getCfgName() {
        return this.cfgName;
    }

    /**
     * Define valor para campo cfgName.
     * 
     * @param cfgName valor para campo cfgName.
     */
    public void setCfgName(String cfgName) {
        this.cfgName = cfgName;
    }

    /**
     * @return valor do campo user.
     */
    @NotNull
    @Column(name = "USERNAME", nullable = false)
    @Documentation("NOME DO USUÁRIO QUE EXECUTOU EXPURGO")
    public String getUserName() {
        return this.userName;
    }

    /**
     * Define valor para campo user.
     * 
     * @param userName valor para campo userName.
     */
    public void setUserName(String userName) {
        this.userName = userName;
    }

    /**
     * @return valor do campo itemsPurged.
     */
    @NotNull
    @Column(name = "TOTAL_ITEMS", nullable = false)
    @Documentation("QUANTIDADE DE ITEMS TOTAL DESSA REQUISIÇÃO DE EXPURGO")
    public Integer getTotalItems() {
        return totalItems;
    }

    /**
     * @param totalItems valor para campo itemsToPurge.
     */
    public void setTotalItems(Integer totalItems) {
        this.totalItems = totalItems;
    }

    /**
     * @return valor do campo itemsPurged.
     */
    @NotNull
    @Column(name = "TOTAL_ITEMS_PURGED", nullable = false)
    @Documentation("QUANTIDADE DE ITEMS EXPURGADOS")
    public Integer getTotalItemsPurged() {
        return totalItemsPurged;
    }

    /**
     * Define valor para campo itemsPurged.
     * 
     * @param totalItemsPurged valor para campo itemsPurged.
     */
    protected void setTotalItemsPurged(Integer totalItemsPurged) {
        this.totalItemsPurged = totalItemsPurged;
    }

    /**
     * Incrementa número de itens expurgados.
     * 
     * @param itemsToAdd número de itens a adicionar.
     */
    public void incItemsPurged(int itemsToAdd) {
        this.totalItemsPurged += itemsToAdd;
    }

    /**
     * @return valor do campo requestStart.
     */
    @Index(suffix = "JT_0")
    @Column(name = "TS_START", nullable = false)
    @Type(type = "bancosys.tec.persist.hibernate.type.TimestampType")
    @Documentation("DATA/HORA DO INÍCIO DA EXECUÇÃO DO EXPURGO")
    public Timestamp getRequestStartTime() {
        return requestStartTime;
    }

    /**
     * Define valor para campo requestStart.
     * 
     * @param requestStartTime valor para campo requestStart.
     */
    public void setRequestStartTime(Timestamp requestStartTime) {
        this.requestStartTime = requestStartTime;
    }

    /**
     * @return valor do campo requestEnd.
     */
    @Column(name = "TS_FINISH")
    @Type(type = "bancosys.tec.persist.hibernate.type.TimestampType")
    @Documentation("DATA/HORA DO TÉRMINO DA EXECUÇÃO DO EXPURGO")
    public Timestamp getRequestEndTime() {
        return requestEndTime;
    }

    /**
     * Define valor para campo requestEnd.
     * 
     * @param requestEndTime valor para campo requestEnd.
     */
    public void setRequestEndTime(Timestamp requestEndTime) {
        this.requestEndTime = requestEndTime;
    }

    /**
     * @return valor do campo status.
     */
    @NotNull
    @Column(name = "ST", nullable = false)
    @Documentation("STATUS DA REQUISIÇÃO DE EXPURGO; 0. RUNNING, 1. OK, 2. ERROR")
    @Constraint(suffix = "0")
    public PurgeStatus getStatus() {
        return status;
    }

    /**
     * Define valor para campo status.
     * 
     * @param status valor para campo status.
     */
    public void setStatus(PurgeStatus status) {
        this.status = status;
    }

    /**
     * @return mensagem de erro.
     */
    @Column(name = "ERROR_MESSAGE")
    @Documentation("MENSAGEM DE ERRO CASO ESSA REQUISIÇÃO DE EXECUÇÃO DE EXPURGO TENHA TERMINADO EM ERRO")
    public String getErrorMessage() {
        return this.errorMessage;
    }

    /**
     * @param errorMessage mensagem de erro.
     */
    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }

    /**
     * @return valor do campo maxBlockSize.
     */
    @NotNull
    @Column(name = "MAX_WINDOW_SIZE", nullable = false)
    @Documentation("TAMANHO MÁXIMO DE JANELA DE EXPURGO USADO NESSA EXECUÇÃO. PODE SER DIFERENTE DO VALOR ATUAL DA CONFIGURAÇÃO")
    public Integer getMaxWindowSize() {
        return maxWindowSize;
    }

    /**
     * Define valor para campo maxWindowSize.
     * 
     * @param maxWindowSize valor para campo maxWindowSize.
     */
    public void setMaxWindowSize(int maxWindowSize) {
        this.maxWindowSize = maxWindowSize;
    }

    /**
     * @return valor do campo maxDate.
     */
    @NotNull
    @Column(name = "MAX_DATE", nullable = false)
    @Documentation("DATA MÁXIMA CONSIDERADA PARA EXECUÇÃO DE EXPURGO")
    @Type(type = "bancosys.tec.persist.hibernate.type.DateType")
    public Date getMaxDate() {
        return maxDate;
    }

    /**
     * Define valor para campo maxDate.
     * 
     * @param maxDate valor para campo maxDate.
     */
    public void setMaxDate(Date maxDate) {
        this.maxDate = maxDate;
    }

    /**
     * @return percentual de itens ja expurgados.
     */
    @Transient
    public int getPurgedItemsPercentage() {
        final int perCent = 100;
        return this.totalItemsPurged * perCent / this.totalItems;
    }

    /**
     * @return numero de itens que ainda nao foram expurgados.
     */
    @Transient
    public int getRemainingItems() {
        return this.totalItems - this.totalItemsPurged;
    }

    /**
     * @return <code>true</code> se status de execucao for RUNNING, <code>false</code> se nao.
     */
    @Transient
    public boolean isRunning() {
        return PurgeStatus.RUNNING.equals(this.status);
    }

    /**
     * @return <code>true</code> se status de execucao for OK, <code>false</code> se nao.
     */
    @Transient
    public boolean isOk() {
        return PurgeStatus.OK.equals(this.status);
    }

    /**
     * @return <code>true</code> se status de execucao for NAO OK, <code>false</code> se nao.
     */
    @Transient
    public boolean isNotOk() {
        return PurgeStatus.NOT_OK.equals(this.status);
    }

    /**
     * @return tempo de duracao de execucao em mili segundos.
     */
    @Transient
    public long getExecutionDuration() {
        Timestamp ts = this.requestEndTime;
        if (this.isRunning()) {
            ts = new Timestamp();
        }
        return ts.getTime() - this.requestStartTime.getTime();
    }
}
